package com.fh.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fh.utils.IpAndPostUtisl;
import com.utils.bean.*;
import com.fh.service.Demo2Service;
import com.fh.feign.Demo2Feign;
import com.fh.utils.JwtUtils;
import com.fh.utils.PasswordUtil;
import com.fh.utils.RedisUtils;
import com.utils.exception.BusinessException;
import com.utils.pulc.ResultBody;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author whf
 * @data 2023年 03月 24日
 */
@Slf4j
@Service
public class Demo2ServiceImpl implements Demo2Service {

    @Autowired
    private Demo2Feign demo2Feign;

    @Autowired
    private PasswordUtil passwordUtil;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private IpAndPostUtisl ipAndPostUtisl;

    /**
     * @param safety
     * @return java.lang.Object
     * @description: 查询密码是否存在
     * @author whf
     * @date 2023/4/25 8:29
     */
    @Override
    public User getSafety(Safety safety) {
        ResultBody<Safety> resultBodySafety = demo2Feign.index(safety);
        if(resultBodySafety.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }
        Safety safetyData = resultBodySafety.getData();
        boolean verify = passwordUtil.verify(safety.getPassword(), safetyData.getPassword());
        if(!verify) {
            throw new BusinessException("账号或密码不正确,请重新输入");
        }
        ResultBody<User> resultBodyUser = demo2Feign.getUser(safety);
        if(resultBodyUser.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }
        User user = resultBodyUser.getData();
        String tokenId = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
        String token = jwtUtils.generateToken(tokenId, user.getUsername());
        user.setToken(token);
        user.setTokenID(tokenId);
        return user;
    }

    /**
     * @param safetyAndUser
     * @description: 注册接口
     * @author whf
     * @date 2023/5/10 15:07
     */
    @GlobalTransactional(rollbackFor = BusinessException.class)
    @Override
    public void setSafetyAndUser(SafetyAndUser safetyAndUser) {
//        注册接口 获取他的用户信息 添加到User中 然后添加到数据库
        User user = new User(safetyAndUser.getUsername(), safetyAndUser.getPhone(), safetyAndUser.getEmail());
        ResultBody<User> userResultBody = demo2Feign.setUser(user);
        if(userResultBody.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }

        //        得到他的账号和密码 并对他的密码进行加密 然后添加到数据库
        String password = passwordUtil.encrypt(safetyAndUser.getPassword());
        Safety safety = new Safety(safetyAndUser.getAccountname(), password);
        ResultBody<Safety> safetyresultBody = demo2Feign.setUser(safety);
        if(safetyresultBody.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }
//      对关联变进行添加 职位默认为2
        User userData = userResultBody.getData();
        Safety safetydata = safetyresultBody.getData();
        Safetyoruser safetyoruser = new Safetyoruser(safetydata.getId(), userData.getId());
        demo2Feign.setSafetyoruser(safetyoruser);

    }

    /**
     * @param substitute
     * @return java.util.List<com.fh.bean.Resource>
     * @description: 通过个人的Id得到他的职位信息
     * @author whf
     * @date 2023/4/26 8:28
     */
    @Override
    public List<Role> selectUID(Substitute substitute) {
        BoundValueOperations<String, String> acthority = redisTemplate.boundValueOps(substitute.getId());
        String role = acthority.get();
        if(StringUtils.hasText(role)) {
            List<Role> roles = JSON.parseArray(role, Role.class);
            return roles;
        }
        ResultBody<List<Role>> rolesResultBody = demo2Feign.selectAll(substitute);
        if(rolesResultBody.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }
        List<Role> roles = rolesResultBody.getData();
        String jsonString = JSON.toJSONString(roles);
        acthority.set(jsonString);
        return roles;
    }

    /**
     * @param substitute
     * @description: 退出的时候删除Redis中的Token
     * @author whf
     * @date 2023/4/26 9:18
     */
    @Override
    public String exitRedis(Substitute substitute) {
        boolean del = redisUtils.del(substitute.getId());
        if(del) {
            return "退出失败,已经不存在该Token";
        }
        String token = redisUtils.getToken(substitute.getId());
        if(StringUtils.hasText(token)) {
            throw new BusinessException("失败了");
        }
        return "退出成功";
    }

    /**
     * @param customerPage
     * @return java.util.List<com.utils.bean.Customer>
     * @description: 分页查询
     * @author whf
     * @date 2023/5/11 8:38
     */
    @Override
    public List<Customer> getCustomerPage(CustomerPage customerPage) {
        if(customerPage.getPosition() == 0){
            // 应该从数据库查到权限 然后再去查询 这样是错误的 随便写了
            return getBoss(customerPage);
        }
        ResultBody<Page<Customer>> page = demo2Feign.page(customerPage);
        if(page.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }
        Page<Customer> resultPage = page.getData();
        List<Customer> records = resultPage.getRecords();
        return records;
    }

    private List<Customer> getBoss(CustomerPage customerPage){
        ResultBody<Page<Customer>> userBoss = demo2Feign.getBoss(customerPage);
        if(userBoss.getCode() != 200) {
            throw new BusinessException("接口出错了");
        }
        Page<Customer> data = userBoss.getData();
        List<Customer> records = data.getRecords();
        return records;
    }

    /**
     * @param customer
     * @description: 对客户进行添加
     * @author whf
     * @date 2023/5/11 14:37
     */
    @Override
    public void save(Customer customer) {
        demo2Feign.save(customer);
    }

    /**
     * @param costomerID
     * @description: 对单个的人员进行删除
     * @author whf
     * @date 2023/5/17 9:25
     */
    @Override
    public void delCustomer(CostomerID costomerID) {
        ResultBody<Object> objectResultBody = demo2Feign.delCostomer(costomerID);
        if(objectResultBody.getCode() != 200) {
            throw new BusinessException("删除失败");
        }
    }

    /**
     * @param costomerIDS
     * @return null
     * @description: 对多个人进行删除
     * @author whf
     * @date 2023/5/17 9:26
     */
    @Override
    public void delCustomers(List<CostomerID> costomerIDS) {
        ResultBody<Object> objectResultBody = demo2Feign.delCostomers(costomerIDS);
        if(objectResultBody.getCode() != 200) {
            throw new BusinessException("删除失败");
        }
    }

    /**
     * @param customer
     * @return java.util.List<com.utils.bean.Customer>
     * @description: 根据条件查询
     * @author whf
     * @date 2023/5/17 10:36
     */
    @Override
    public List<Customer> getCustomerIF(Customer customer) {
        if(customer.getUserId() == null || customer.getUserId() <= 0) {
            throw new BusinessException("不允许查询");
        }
        ResultBody<List<Customer>> customerIF = demo2Feign.getCustomerIF(customer);
        if(customerIF.getCode() != 200){
            throw new BusinessException("出现错误");
        }
        return customerIF.getData();
    }

    /**
     * @param multipartFileImag
     * @return com.utils.pulc.ResultBody<java.util.List < java.lang.String>>
     * @description: 将图片保存在 static 文件下 然后把名字进行保存(数据库)
     * @author whf
     * @date 2023/5/31 8:50
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public String setMultipartFile(MultipartFileImag multipartFileImag) {
         /*
        这个添加吧 如果可以随便添加 都可以看到 那就可以的
        如果是 只能看到一张图片 那就要先查一下 看看 abandon 有没有为 1的
        如果有那就不让他添加 没有才可以添加(或者让前端做判断)
         */
//        得到当前路径
        String imgPath = ipAndPostUtisl.getImgPath();
//        得到MultipartFile 可以保存图片
        MultipartFile multipartFile = multipartFileImag.getMultipartFile();
//        得到图片关联的用户
        Integer id = multipartFileImag.getId();
//        得到图片的名字
        String name = multipartFile.getOriginalFilename();
//        得到以.为结尾的索引
        int lasted = name.lastIndexOf(".");
//        头部是从0到.结尾
//        结尾
        String suffix = name.substring(lasted);
//        把图片的名字 加入UUID 进行保存
//        防止重名(为了防止图片的名字过长所以只使用UUID的1位名字)
        String pictureName = UUID.randomUUID().toString().replace("-", "");
//        将图片的信息进行保存
        Images images = new Images(pictureName,suffix,id,1);
//        调用接口进行保存
        demo2Feign.setMultipartFile(images);
        try {
//            将图片存储到指定地址
            multipartFile.transferTo(new File(imgPath + "/" + pictureName + suffix));
        } catch(IOException e) {
            throw new RuntimeException(e);
        }
//        得到当前的Ip跟端口号
        String ipAndPost = ipAndPostUtisl.getIpAndPost();
//        返回静态地址
        return  ipAndPost  + pictureName + suffix;
    }

    /**
     * @description: 对保存的图片地址进行查询
     * @author whf
     * @date 2023/6/1 15:11
     * @param imagesOrUser
     * @return java.util.List<java.lang.String>
     */
    @Override
    public List<Photograph> getImage(ImagesOrUser imagesOrUser) {
        ResultBody<List<Images>> image = demo2Feign.getImage(imagesOrUser);
        if(image.getCode() != 200) {
            throw new BusinessException("接口出错");
        }
        List<Images> images = image.getData();
        ArrayList<Photograph> photographs = new ArrayList<>();
        String ipAndPost = ipAndPostUtisl.getIpAndPost();
//        使用Stream流进行遍历
        images.stream().forEach(im-> {
//            得到图片的名字 因为存储的时候 是分开存储的 顺便进行拼装
            String pictureName = ipAndPost + im.getName() + im.getSuffix();
            photographs.add(new Photograph(im.getAbandon(),pictureName));
        });
        return photographs;
    }

    /**
     * @param imagesUpdate
     * @return com.utils.pulc.ResultBody<java.lang.Object>
     * @description: 对图片进行删除
     * @author whf
     * @date 2023/6/1 17:23
     */
    @Override
    public void updateImages(ImagesUpdate imagesUpdate) {
        ResultBody<Object> obj = demo2Feign.updateImages(imagesUpdate);
        if(obj.getCode() != 200) {
            throw new BusinessException("接口出现问题");
        }
    }

    @Override
    @GlobalTransactional(rollbackFor = BusinessException.class)
    @Transactional
    public void updateMoney(MoneyAll moneyAll) {
        Money money = new Money(moneyAll.getId(), moneyAll.getMoney());
        demo2Feign.updateMoney(money);
        if(moneyAll.getTransferId() == 3){
            throw new BusinessException("回滚了吗");
        }
        Money money1 = new Money(moneyAll.getTransferId(), moneyAll.getTransferMoney());
        demo2Feign.updateMoney(money1);
    }


}
